﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;

namespace TV_Agenda_V2.Objects
{
    public class Show
    {
        #region Variables
        private Episode prev;
        private Episode next;
        
        public Int32 ID { get; set; }
        public String Name { get; set; }
        public String Link { get; set; }
        public String Country { get; set; }
        public String Started { get; set; }
        public String Ended { get; set; }
        public Int32 NumberOfSeasons { get; set; }
        public String Status { get; set; }
        public String Classification { get; set; }
        public Int32 Runtime { get; set; }
        public String Network { get; set; }
        public String NetworkCountry { get; set; }
        public String AirTime { get; set; }
        public String AirDay { get; set; }
        public String Timezone { get; set; }
        public List<Aka> Akas { get; set; }
        public List<String> Genres { get; set; }
        public List<Season> Seasons { get; set; }
        #endregion

        public Show()
        {
            Akas = new List<Aka>();
            Genres = new List<String>();
            Seasons = new List<Season>();
        }

        public Show ShowInstance { get { return this; } }

        /// <summary>
        /// Gets the time difference.
        /// </summary>
        /// <value>The time difference.</value>
        public Int32 TimeDifference
        {
            get
            {
                if (String.IsNullOrEmpty(Timezone) || Timezone.Length < 6)
                    return 0;

                String tmp = Timezone.Substring(3, 3);
                return Int32.Parse(tmp);
            }
        }

        /// <summary>
        /// Gets the local air time.
        /// </summary>
        /// <value>The local air time.</value>
        public String LocalAirTime
        {
            get
            {
                if (String.IsNullOrEmpty(AirDay) || String.IsNullOrEmpty(AirTime))
                    return null;
                DateTime dt = DateTime.ParseExact(DateTime.Now.ToString("dd-MM-yyyy") + " " + AirTime, "dd-MM-yyyy HH:mm", null);
                dt = dt.AddHours(TimeZoneInfo.Local.BaseUtcOffset.Hours - TimeDifference);
                return dt.ToString("HH:mm");
            }
        }

        /// <summary>
        /// Gets the local air day.
        /// </summary>
        /// <value>The local air day.</value>
        public String LocalAirDay
        {
            get
            {
                if (String.IsNullOrEmpty(AirDay) || String.IsNullOrEmpty(AirTime))
                    return null;
                DateTime dt = DateTime.ParseExact(DateTime.Now.ToString("dd-MM-yyyy") + " " + AirTime, "dd-MM-yyyy HH:mm", null);
                DayOfWeek before = dt.DayOfWeek;
                dt = dt.AddHours(TimeZoneInfo.Local.BaseUtcOffset.Hours - TimeDifference);
                DayOfWeek after = dt.DayOfWeek;
                DayOfWeek dow = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), AirDay, true);
                dow += after - before;
                return dow.ToString();
            }
        }

        /// <summary>
        /// Gets the previous episode as a string.
        /// </summary>
        /// <value>The previous episode as a string.</value>
        public String PreviousEpisodeString
        {
            get
            {
                Episode prev = PreviousEpisode;
                if (prev == null)
                    return "";
                else
                    return prev.ToString();
            }
        }

        /// <summary>
        /// Gets or sets the previous episode.
        /// </summary>
        /// <value>The previous episode.</value>
        public Episode PreviousEpisode
        {
            set
            {
                prev = value;
            }
            get
            {
                if (prev == null)
                    UpdatePreviousEpisode();
                return prev;
                
            }
        }

        /// <summary>
        /// Updates the previous episode.
        /// </summary>
        public void UpdatePreviousEpisode()
        {
            DateTime closest = DateTime.MinValue;
            DateTime airDate;
            prev = null;
            foreach (Season season in Seasons)
            {
                foreach (Episode episode in season.Episodes)
                {
                    if (!DateTime.TryParse(episode.AirDate, out airDate))
                        continue;
                    if (airDate < DateTime.Now.Date && airDate > closest)
                    {
                        prev = episode;
                        closest = airDate;
                    }
                }
            }
        }

        /// <summary>
        /// Gets the next episode date.
        /// </summary>
        /// <value>The next episode date.</value>
        public DateTime NextDate
        {
            get
            {
                Episode ep = NextEpisode;
                if (ep == null)
                    return DateTime.MaxValue;
                else
                {
                    DateTime airDate;
                    if (!DateTime.TryParse(ep.AirDate, out airDate))
                        return DateTime.MaxValue;
                    return airDate;
                }
            }
        }

        /// <summary>
        /// Gets the next episode as a string.
        /// </summary>
        /// <value>The next episode as a string.</value>
        public String NextEpisodeString
        {
            get
            {
                Episode next = NextEpisode;
                if (next == null)
                    return "";
                else
                    return next.ToString();
            }
        }


        /// <summary>
        /// Gets or sets the next episode.
        /// </summary>
        /// <value>The next episode.</value>
        public Episode NextEpisode
        {
            set
            {
                next = value;
            }
            get
            {
                if (next == null)
                    UpdateNextEpisode();
                return next;
            }
        }

        /// <summary>
        /// Updates the next episode.
        /// </summary>
        public void UpdateNextEpisode()
        {
            DateTime closest = DateTime.MaxValue;
            DateTime airDate;
            next = null;
            foreach (Season season in Seasons)
            {
                foreach (Episode episode in season.Episodes)
                {
                    if (!DateTime.TryParse(episode.AirDate, out airDate))
                        continue;
                    if (airDate >= DateTime.Now.Date && airDate < closest)
                    {
                        next = episode;
                        closest = airDate;
                    }
                }
            }
        }

        public override string ToString()
        {
            return Name;
        }
    }
}
